package com.xadrez.modelo;

import com.xadrez.Principal;
import com.xadrez.ia.IA;
import java.util.ArrayList;
import java.util.List;

public abstract class Peca {

    private Jogador jogador;
    private boolean ativa;
    private Posicao posicaoNoTabuleiro;

    public Peca() {
    }

    public Peca(Jogador jogador) {
        this.jogador = jogador;
        ativa = true;
    }
    
    // <editor-fold defaultstate="collapsed" desc="MÉTODOS DE MOVIMENTAÇÃO">
    //Desloca a peça para alguma posição. ou para COMER ou para MOVER
    public boolean deslocaPeca(Posicao posicao) {
        boolean moveu = true;
        int x = posicao.getX();
        int y = posicao.getY();

        //Ele só pode mover a peça para uma posicoes que esteja dentro do alcance da mesma
        if (podeMover(posicao)) {
            Tabuleiro tabuleiro = Principal.getTabuleiro();
            Peca pecaNaPosicaoXY = tabuleiro.getQuadrados()[x][y];

            if (pecaNaPosicaoXY != null) {
                if (pecaNaPosicaoXY.getJogador() instanceof IA) {
                    come(pecaNaPosicaoXY);
                }
            } else {
                move(posicao);
            }
        } else {
            moveu = false;
        }

        return moveu;
    }

    private void move(Posicao posicao) {
        Tabuleiro tabuleiro = Principal.getTabuleiro();

        int i = this.getPosicaoNoTabuleiro().getX();
        int j = this.getPosicaoNoTabuleiro().getY();
        int x = posicao.getX();
        int y = posicao.getY();

        //Posicionamos no novo quadrado
        tabuleiro.getQuadrados()[x][y] = this;
        //Removemos peca do quadrado antigo
        tabuleiro.getQuadrados()[i][j] = null;
        //Atualizamos o atributo posicao da peca
        this.setPosicaoNoTabuleiro(posicao);

        //Se for peao devemos setar que gastou seu primeiro movimento
        if ((this instanceof Peao) && (((Peao) this).isPrimeiroMovimento())) {
            ((Peao) this).setPrimeiroMovimento(false);
        }
    }

    private void come(Peca pecaASerComida) {
        Tabuleiro tabuleiro = Principal.getTabuleiro();

        int x = pecaASerComida.getPosicaoNoTabuleiro().getX();
        int y = pecaASerComida.getPosicaoNoTabuleiro().getY();
        tabuleiro.getQuadrados()[x][y] = this;

        x = this.getPosicaoNoTabuleiro().getX();
        y = this.getPosicaoNoTabuleiro().getY();
        tabuleiro.getQuadrados()[x][y] = null;

        this.setPosicaoNoTabuleiro(pecaASerComida.getPosicaoNoTabuleiro());

        //Se for peao devemos setar que gastou seu primeiro movimento
        if ((this instanceof Peao) && (((Peao) this).isPrimeiroMovimento())) {
            ((Peao) this).setPrimeiroMovimento(false);
        }
    }

    //Esse método verifica se a peca pode ser movida para a casa (x,y) do tabuleiro
    private boolean podeMover(Posicao posicao) {
        boolean confirma = false;
        List<Posicao> lista = new ArrayList<Posicao>();

        lista = this.recuperaMovimentosPossiveis();

        if (lista != null) {
            int i = 0;
            while (i < lista.size() && !confirma) {
                if (lista.get(i).getX() == posicao.getX()
                        && lista.get(i).getY() == posicao.getY()) {
                    confirma = true;
                }
                i++;
            }
        }

        return confirma;
    }
    // </editor-fold>

    //Recupera uma lista de movimentos posiveis para determinada peca
    public abstract List<Posicao> recuperaMovimentosPossiveis();

    // <editor-fold defaultstate="collapsed" desc="GETs e SETs">
    public Jogador getJogador() {
        return jogador;
    }

    public void setJogador(Jogador jogador) {
        this.jogador = jogador;
    }

    public boolean isAtiva() {
        return ativa;
    }

    public void setAtiva(boolean ativa) {
        this.ativa = ativa;
    }

    public Posicao getPosicaoNoTabuleiro() {
        return posicaoNoTabuleiro;
    }

    public void setPosicaoNoTabuleiro(Posicao posicaoNoTabuleiro) {
        this.posicaoNoTabuleiro = posicaoNoTabuleiro;
    }

    public boolean isPosicaoDentroDosLimites(Posicao posicao) {
        boolean confirma = false;
        if (posicao.getX() < 8 && posicao.getY() >= 0 && posicao.getY() < 8 && posicao.getY() >= 0) {
            confirma = true;
        }
        return confirma;
    }
    // </editor-fold>
}
